/* eslint-disable global-require */
/* eslint-disable import/no-dynamic-require */
import path from 'path';
import type { RollupOptions } from 'rollup';
// @ts-ignore
import urlPlugin from '@rollup/plugin-url';
// @ts-ignore
import postcssImport from 'postcss-import';
// @ts-ignore
import LessPluginImportNodeModules from 'less-plugin-import-node-modules';
import aliasPlugin from '@rollup/plugin-alias';
import replacePlugin from '@rollup/plugin-replace';
import nodeResolvePlugin from '@rollup/plugin-node-resolve';
import commonjsPlugin from '@rollup/plugin-commonjs';
import jsonPlugin from '@rollup/plugin-json';
import seeplnIcon from 'vite-plugin-seepln-icon';
import copyPlugin from 'rollup-plugin-copy';
import postcssPlugin from 'rollup-plugin-postcss';
import { theme as baseTheme } from '@deepfos/theme';
import { isNull } from 'lodash';
import visualizer from 'rollup-plugin-visualizer';
import { DEFAULT_EXTENSIONS, DEFAULT_MAIN_FIELDS } from './constants';
import type { BuildOptions } from './build';
import type { Logger } from './logger';
import { buildReporterPlugin } from './plugins/reporter';
import { esbuildPlugin, buildEsbuildPlugin } from './plugins/esbuild';
import importPlugin from './plugins/import';
import { getExternals } from './vitePluginSeepln';

export const external = [
  'ahooks',
  'immer',
  'lodash',
  'moment',
  'react',
  'react-dom',
  'react-router-dom',
  'styled-components',
];

/**
 * 合并配置
 */
export async function resolveConfig(
  buildOptions: BuildOptions,
  logger: Logger,
): Promise<RollupOptions> {
  const {
    root,
    base,
    mode,
    target,
    sourcemap,
    analyze,
    antPrefix,
    theme,
    alias,
    replace,
    rollupOptions,
    deepfosEnv,
  } = buildOptions;
  const pkg = require(path.resolve(root, 'package.json'));

  // 元素组件模式
  const isElementModule = target === 'element';
  const versionName = pkg.version.replace(/\./g, '-');
  const isDev = mode === 'development';

  // 元素组件版本号目录
  const outDir = isElementModule ? `dist/${versionName}` : 'dist';

  const BASE_URL =
    base || (isElementModule ? `/${pkg.name}/${pkg.version.replace(/\./g, '-')}/` : '/');

  // html 输出路径
  const outputHTMLEntry = path.join('/', BASE_URL, `/$1.js?t=${Date.now()}`);
  // package-base内的外部依赖相关
  const { externalNames, externalAliases } = await getExternals(deepfosEnv);
  const realExternal: string[] = externalNames.concat((rollupOptions?.external as string[]) || []);
  return {
    ...rollupOptions,
    input: rollupOptions?.input || ['src/main.tsx'],
    output: {
      dir: outDir,
      sourcemap: sourcemap || false,
      // 元素组件打包为 system 格式
      format: isElementModule ? 'system' : undefined,
      paths: externalAliases,
      ...rollupOptions?.output,
    },
    // 外部依赖
    // external: isElementModule
    //   ? external.concat((rollupOptions?.external as string[]) || [])
    //   : rollupOptions?.external,
    external: realExternal,
    preserveEntrySignatures: 'strict',
    plugins: [
      aliasPlugin({
        entries: {
          lodash: 'lodash-es',
          'lodash.debounce': 'lodash-es/debounce',
          'lodash.throttle': 'lodash-es/throttle',
          '@': path.resolve(root, 'src'),
          ...(alias as Record<string, string> | undefined),
        },
      }),
      replacePlugin({
        preventAssignment: true,
        delimiters: ['', ''],
        'process.env.NODE_ENV': JSON.stringify(mode || 'production'),
        'import.meta.env.VITE_SEEPLN_ENV': JSON.stringify(process.env.VITE_SEEPLN_ENV),
        'import.meta.env.BASE_URL': JSON.stringify(BASE_URL),
        'import.meta.env.DEV': JSON.stringify(isDev),
        'import.meta.env.PROD': JSON.stringify(!isDev),
        ...replace,
      }),
      nodeResolvePlugin({
        mainFields: DEFAULT_MAIN_FIELDS,
        browser: true,
        preferBuiltins: false,
        extensions: DEFAULT_EXTENSIONS,
      }),
      commonjsPlugin(),
      jsonPlugin(),
      importPlugin({
        libraryName: '@ant-design/icons',
        libraryDirectory: 'es/icons',
        camel2DashComponentName: false,
      }),
      ...(realExternal.includes('antd')
        ? []
        : [
            importPlugin({
              libraryName: 'antd',
              style: true,
            }),
          ]),
      esbuildPlugin({
        exclude: ['**/node_module/@babel/standalone/**', '**/node_module/ace-builds/**'],
      }),
      urlPlugin({
        limit: 1024 * 40,
      }),
      seeplnIcon(),
      postcssPlugin({
        plugins: [postcssImport()],
        // @ts-ignore
        use: {
          less: {
            modifyVars: {
              ...baseTheme,
              ...theme,
              '@ant-prefix': antPrefix || pkg.name,
            },
            javascriptEnabled: true,
            plugins: [new LessPluginImportNodeModules()],
          },
        },
        autoModules: true,
        extensions: ['.css', '.less'],
        modules: false,
      }),
      // 不解析需要保留的 import()
      {
        name: 'retain-import-expression',
        renderDynamicImport({ targetModuleId }) {
          if (isNull(targetModuleId)) {
            return {
              left: 'import(',
              right: ')',
            };
          }
          return undefined;
        },
      },
      copyPlugin({
        targets: [
          // 元素组件生成版本号目录
          { src: 'public/*', dest: outDir },
          // 元素组件无需自己的 index.html
          ...(isElementModule
            ? []
            : [
                {
                  src: 'index.html',
                  transform: (contents: Buffer) =>
                    contents
                      .toString()
                      // 替换入口
                      .replace(
                        /<script\s*type\s*=\s*"module"\s*src\s*=\s*"\/src\/([\w-]+)\.tsx"\s*>.*?<\/script>/gims,
                        `<script type="module" crossorigin src="${outputHTMLEntry}"></script>`,
                      ),
                  dest: 'dist',
                },
              ]),
        ],
      }),
      // 生产环境启用压缩
      buildEsbuildPlugin({ minify: !isDev }),
      // 可视化分析
      ...(analyze
        ? [
            visualizer({
              filename: 'stats_rollup.html',
            }),
          ]
        : []),
      ...(rollupOptions?.plugins || []),
      buildReporterPlugin({ root, logger, outDir }),
    ],
  };
}
